﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace Asset
{

    public enum Pool_Type
    {
        None,
        Model,
        UI,
        Effect,
    }

    public class BasePool
    {
        protected string resUrl;
        protected string resName;
        protected Queue<GameObject> cachePool = new Queue<GameObject>();
        protected List<Action<GameObject>> handlerPool = new List<Action<GameObject>>();
        protected UnityEngine.Object tempObj;
        protected Transform root;

        public BasePool(string resUrl, string resName)
        {
            this.resUrl = resUrl;
            this.resName = resName;
            root = new GameObject(resUrl).transform;
            root.SetParent(PoolRoot.Instance.Root);
            root.localPosition = Vector3.zero;
        }

        //同步获取
        public GameObject getObj()
        {
            if (cachePool.Count > 0)
            {
                return cachePool.Dequeue();
            }
            tempObj = ResPool.Instance.loadAsset<UnityEngine.Object>(resUrl, resName);
            GameObject go = GameObject.Instantiate(tempObj) as GameObject;
            go.AddComponent<PoolObj>().ResUrl = this.resUrl;
            return go;
        }
        //异步
        public void getObjAsync(Action<GameObject> handler, bool useCache = true)
        {
            if (cachePool.Count > 0 && useCache)
            {
                handler(cachePool.Dequeue());
            }
            else
            {
                handlerPool.Add(handler);
                ResPool.Instance.loadAssetAsync<UnityEngine.Object>(resUrl, resName).onComplete += loadFinish;
            }
        }

        public void unload(Action<GameObject> handler)
        {
            if (handlerPool.Contains(handler))
            {
                handlerPool.Remove(handler);
            }
        }

        private void loadFinish(UnityEngine.Object obj)
        {
            tempObj = obj;
        }

        public int tick(int maxNum)
        {
            if (tempObj == null) return 0;
            if (handlerPool.Count <= 0)
            {
                return 0;
            }
            maxNum = Math.Min(maxNum, handlerPool.Count);
            for (int i = 0; i < maxNum; i++)
            {
                GameObject go = GameObject.Instantiate(tempObj) as GameObject;
                go.AddComponent<PoolObj>().ResUrl = this.resUrl;
                handlerPool[i](go);
            }
            for (int i = maxNum - 1; i >= 0; i--)
            {
                handlerPool.RemoveAt(i);
            }
            return maxNum;
        }

        public void recyleObj(GameObject obj)
        {
            obj.transform.SetParent(this.root);
            obj.transform.localPosition = Vector3.zero;
            onRecyle(obj);
            cachePool.Enqueue(obj);
        }

        int preLoadNeedCount = 0;
        int preLoadNowCount = 0;
        Action preLoadHandler;
        public void preLoad(int count, Action callBack)
        {
            preLoadNeedCount = count;
            preLoadNowCount = this.cachePool.Count;
            preLoadHandler = callBack;
            if (preLoadNowCount >= preLoadNeedCount)
            {
                preLoadHandler();
                preLoadHandler = null;
            }
            else
            {
                int need = preLoadNeedCount - preLoadNowCount;
                for (int i = 0; i < need; i++)
                {
                    this.getObjAsync(onPreLoad, false);
                }
            }
        }

        private void onPreLoad(GameObject obj)
        {
            preLoadNowCount++;
            if (preLoadNowCount >= preLoadNeedCount)
            {
                preLoadHandler();
                preLoadHandler = null;
            }
            recyleObj(obj);
        }

        //Prefab的组件 禁用todo 禁用Anim
        protected virtual void onRecyle(GameObject obj)
        {

        }

        public virtual void dispose()
        {
            tempObj = null;
        }

    }

}
